package com.it.chinasoft.service.activiti;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.ActivitiRule;
import org.junit.Rule;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MultiApproval {

    @Rule
    public ActivitiRule activitiRule = new ActivitiRule("activiti.cfg.xml");

    /**
     * 获取默认流程引擎实例，会自动读取activiti.cfg.xml文件
     */
    private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    private final static Logger logger = LoggerFactory.getLogger(MultiApproval.class);

    /**
     * 部署流程定义
     */
    @Test
    public void deployFlow() throws FileNotFoundException, FileNotFoundException {
        RepositoryService repositoryService = processEngine.getRepositoryService();

        FileInputStream bpmnStream = new FileInputStream("D:\\Programming\\Projects\\prusa\\src\\main\\resources\\processes\\multiApproval.xml");
        //得到流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        processEngine.getRepositoryService()
                .createDeployment()
                .name("员工发起请假")
                .addInputStream("multiApprovalbpmn", bpmnStream)
                .deploy();
        //注意：inputStream不能带后缀，FileInputStream用全称。
        logger.info("部署工作流成功！");

    }

    /**
     * 启动刚刚部署的流程。
     */
    @Test
    public void StartProcessInstance() {

        Map<String, Object> situation=new HashMap<String,Object>();
        situation.put("msg", "common");
        processEngine.getRuntimeService()
                .startProcessInstanceByKey("multiApproval",situation);  //这个是act_re_procdef表ID
        logger.info("程序员典韦发起请假电子流");
    }

    /**
     * 申请者Dianwei查询当前正在执行的任务，并返回查询得到的信息。
     */
    @Test
    public void applierQueryTask() {
        List<Task> tasks = processEngine.getTaskService()
                .createTaskQuery()
                .taskAssignee("Dianwei")
                .list();
        for (Task task : tasks) {
            logger.info("task明细:" + String.valueOf(task));
        }
    }

    /**
     * 申请者完成节点任务
     */
    @Test
    public void applierFinishTask(){
        //different situations
        Map<String, Object> situation=new HashMap<String,Object>();
        situation.put("days", 3);
        processEngine.getTaskService()
                .complete("192504",situation); //查看act_ru_task数据表id
        logger.info("Dianwei提交完成申请，检测谁进行下一步审批。");
    }

    @Test
    public void approverQueryTask() {
        List<Task> tasks = processEngine.getTaskService()
                .createTaskQuery()
                .taskAssignee("Xiahoudun")
                .list();
        for (Task task : tasks) {
            logger.info("task明细:" + String.valueOf(task));
        }
    }

    @Test
    public void commonTest(){
        reverseTask("192504");
    }

    /**
     * 改变节点流向
     */
    public void reverseTask(String taskId){
        // 得到历史服务组件
        HistoryService historyService = processEngine.getHistoryService();
        HistoricTaskInstance hisTask = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
        if (null == hisTask) {
            logger.error("无效任务ID[ " + taskId + " ]");
        }
        //流程控制服务，查询流程实例(ProcessInstance)与执行流(Execution)
        RuntimeService runtimeService = processEngine.getRuntimeService();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(hisTask.getProcessInstanceId()).singleResult();
        if (null == processInstance) {
            logger.error("该流程已完成!无法回退");
        }
        // 获取流程存储服务定义对象
        RepositoryService repositoryService = activitiRule.getRepositoryService();  //获取RepositoryService对象
        BpmnModel bpmnModel = repositoryService.getBpmnModel(hisTask.getProcessDefinitionId());
        Process process = bpmnModel.getProcesses().get(0);
        //获取到所有的task
        TaskService taskService = processEngine.getTaskService();
        List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list();

        FlowNode sourceNode = (FlowNode) process.getFlowElement(hisTask.getTaskDefinitionKey());
        for(Task obj: taskList){
            FlowNode currentNode = (FlowNode) process.getFlowElement(obj.getTaskDefinitionKey());
            // 获取原本流程连线
            List<SequenceFlow> outComingSequenceFlows = currentNode.getOutgoingFlows();

            // 配置反转流程连线
            SequenceFlow sequenceFlow = new SequenceFlow();
            sequenceFlow.setTargetFlowElement(sourceNode);
            sequenceFlow.setSourceFlowElement(currentNode);
            sequenceFlow.setId("callback-flow");

            List<SequenceFlow> newOutComingSequenceFlows = new ArrayList<>();
            newOutComingSequenceFlows.add(sequenceFlow);
            currentNode.setOutgoingFlows(newOutComingSequenceFlows);

            // 配置任务审批人
            //Map<String, Object> variables = new HashMap<>(1);
            //variables.put("assignee", "Caocao");
            // 完成任务
            taskService.complete(obj.getId());
            // 复原流程
            currentNode.setOutgoingFlows(outComingSequenceFlows);
        }
    }


}

/**
 * @params curTask 即当前任务
 */
